package com.hugh.glrpcconsumer.proxy;

import com.alibaba.fastjson.JSON;
import com.google.common.base.Stopwatch;
import com.hugh.commom.RpcRequest;
import com.hugh.commom.RpcResponse;
import com.hugh.commom.delayqueue.DelayQueueManager;
import com.hugh.commom.delayqueue.DelayTask;
import com.hugh.commom.netty.client.handle.diapatcher.OperationResultFuture;
import com.hugh.commom.netty.client.handle.diapatcher.RequestPendingCenter;
import com.hugh.commom.selector.ChannelFutureEntity;
import com.hugh.commom.selector.ChannelSelect;
import com.hugh.commom.util.IdUtil;
import com.hugh.commom.zk.client.ZkRpcHandle;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.util.concurrent.TimeUnit;

/**
 * @Author: Hugh
 * @Date: 2020/6/14
 */
@Slf4j
@Component
public class ProxyFactory {

    @Autowired
    private ChannelSelect channelSelect;

    @Autowired
    private ZkRpcHandle zkUtill;

    @Autowired
    private DelayQueueManager delayQueueManager;
    // serviceClass 接口类型,根据哪个接口生成子类代理对象;
    public Object createProxy(Class<?> serviceClass, final String providerService){
        return Proxy.newProxyInstance(Thread.currentThread().getContextClassLoader(),
                new Class[]{serviceClass}, new InvocationHandler() {
                    @Override
                    public Object invoke(Object o, Method method, Object[] objects) throws Throwable {
                        method.setAccessible(Boolean.TRUE);
                        //1)选择客户端
                        ChannelFutureEntity select = channelSelect.select(providerService);

                        //2)封装请求参数
                        RequestPendingCenter requestPendingCenter = new RequestPendingCenter();
                        //获取本次的请求id
                        Long requestId = IdUtil.nextId();
                        OperationResultFuture operationResultFuture = new OperationResultFuture();

                        RpcRequest rpcRequest = new RpcRequest();
                        rpcRequest.setMethodName(method.getName());
                        rpcRequest.setClassName(serviceClass.getName());
                        rpcRequest.setParameters(objects);
                        rpcRequest.setParameterTypes(method.getParameterTypes());
                        rpcRequest.setRequestId(requestId);
                        requestPendingCenter.add(requestId, operationResultFuture);
                        log.info("client 构造完clientHandler：{}", JSON.toJSON(rpcRequest));
                        Stopwatch stopwatch = Stopwatch.createStarted();
                        select.getChannelFuture().channel().writeAndFlush(rpcRequest);
                        //3)异步写操作,并返回结果
                        RpcResponse rpcResponse = operationResultFuture.get();
                        select.setRt(stopwatch.elapsed(TimeUnit.MILLISECONDS));
                        zkUtill.upDateZkNodeRt(select);
                        delayQueueManager.put(new DelayTask(select, 1000));
                        log.info("本地调用返回结果：{}, 用时:{}ms", JSON.toJSON(rpcResponse), select.getRt());
                        //4)return 结果
                        return rpcResponse.getResponse();
                    }
                });
    }

}
